<?php

require_once 'vendor/autoload.php';

use Smalot\Cups\Builder\Builder;
use Smalot\Cups\Manager\JobManager;
use Smalot\Cups\Manager\PrinterManager;
use Smalot\Cups\Model\Job;
use Smalot\Cups\Transport\Client;
use Smalot\Cups\Transport\ImprovedClient;
use Smalot\Cups\Transport\ResponseParser;
use Http\Client\Socket\Client as HttpClient;

/**
 * EPSON L4260 Series 打印机专用测试脚本
 * 
 * 此脚本专门用于测试 EPSON L4260 Series 打印机的连接和打印功能
 */

class EpsonL4260Tester {
    private $builder;
    private $client;
    private $httpClient;
    private $responseParser;
    private $jobManager;
    private $printerManager;
    
    // EPSON L4260 可能的连接方式
    private $connectionMethods = [
        'usb' => 'usb://EPSON/L4260%20Series',
        'network_auto' => 'ipp://EPSON-L4260.local:631/ipp/print',
        'network_ip' => 'ipp://10.1.0.21:631/ipp/print', // 需要替换为实际IP
        'cups_local' => 'ipp://localhost:631/printers/EPSON_L4260_Series',
        'windows_wsd' => 'WSD-295647b5-3c1e-435d-bd9e-4b61735be713' // 从测试结果中获取
    ];
    
    public function __construct() {
        $this->builder = new Builder();
        $this->client = new Client();
        $this->httpClient = new HttpClient();
        $this->responseParser = new ResponseParser();
        $this->jobManager = new JobManager($this->builder, $this->httpClient, $this->responseParser);
        $this->printerManager = new PrinterManager($this->builder, $this->httpClient, $this->responseParser);
    }
    
    /**
     * 检测 EPSON L4260 的网络连接
     */
    public function detectNetworkConnection() {
        echo "🔍 检测 EPSON L4260 网络连接...\n\n";
        
        // 方法1: 尝试通过 mDNS 发现
        echo "1. 尝试 mDNS 自动发现:\n";
        $this->tryMdnsDiscovery();
        
        // 方法2: 扫描常见IP段
        echo "\n2. 扫描本地网络IP段:\n";
        $this->scanLocalNetwork();
        
        // 方法3: 检查Windows WSD连接
        echo "\n3. 检查Windows WSD连接:\n";
        $this->checkWindowsWSD();
    }
    
    private function tryMdnsDiscovery() {
        $mdnsHosts = [
            'EPSON-L4260.local',
            'EPSONL4260.local',
            'L4260.local'
        ];
        
        foreach ($mdnsHosts as $host) {
            echo "   尝试连接: $host\n";
            
            // 尝试ping
            $pingResult = $this->pingHost($host);
            if ($pingResult) {
                echo "   ✓ $host 响应正常\n";
                
                // 尝试IPP端口
                if ($this->checkPort($host, 631)) {
                    echo "   ✓ IPP端口631开放\n";
                    $this->testIppConnection("ipp://$host:631/ipp/print");
                }
            } else {
                echo "   ❌ $host 无响应\n";
            }
        }
    }
    
    private function scanLocalNetwork() {
        // 获取本机IP来确定网段
        $localIp = $this->getLocalIp();
        if (!$localIp) {
            echo "   ❌ 无法获取本机IP地址\n";
            return;
        }
        
        echo "   本机IP: $localIp\n";
        
        // 提取网段
        $ipParts = explode('.', $localIp);
        $networkBase = $ipParts[0] . '.' . $ipParts[1] . '.' . $ipParts[2];
        
        echo "   扫描网段: $networkBase.1-254\n";
        echo "   (这可能需要一些时间...)\n";
        
        // 扫描常见的打印机IP
        $commonIps = [100, 101, 102, 103, 104, 105, 110, 150, 200, 201, 202];
        
        foreach ($commonIps as $lastOctet) {
            $testIp = "$networkBase.$lastOctet";
            
            if ($this->checkPort($testIp, 631, 1)) { // 1秒超时
                echo "   ✓ 发现IPP服务: $testIp:631\n";
                $this->testIppConnection("ipp://$testIp:631/ipp/print");
            }
        }
    }
    
    private function checkWindowsWSD() {
        echo "   检查Windows WSD连接...\n";
        
        // 从之前的测试结果中我们知道WSD端口
        $wsdPort = 'WSD-295647b5-3c1e-435d-bd9e-4b61735be713';
        echo "   WSD端口: $wsdPort\n";
        
        // 在Windows上，我们可以尝试直接使用系统打印机
        if (PHP_OS_FAMILY === 'Windows') {
            echo "   ✓ 检测到Windows环境，可以使用系统打印机\n";
            $this->testWindowsPrinting();
        }
    }
    
    /**
     * 测试IPP连接
     */
    private function testIppConnection($uri) {
        echo "   测试IPP连接: $uri\n";
        
        try {
            // 创建测试任务
            $job = new Job();
            $job->setName('EPSON L4260 连接测试');
            $job->setUsername('testuser');
            $job->setCopies(1);
            $job->setPrinterUri($uri);
            $job->addText('EPSON L4260 连接测试\n时间: ' . date('Y-m-d H:i:s'));
            
            echo "   ✓ IPP连接配置成功\n";
            echo "   📝 可用的打印机URI: $uri\n";
            
            return true;
            
        } catch (Exception $e) {
            echo "   ❌ IPP连接失败: " . $e->getMessage() . "\n";
            return false;
        }
    }
    
    /**
     * 测试Windows系统打印
     */
    private function testWindowsPrinting() {
        echo "   尝试Windows系统打印...\n";
        
        // 创建测试文件
        $testFile = 'epson_test.txt';
        $content = "EPSON L4260 Series 测试打印\n" .
                  "时间: " . date('Y-m-d H:i:s') . "\n" .
                  "如果您看到这个文档，说明打印功能正常！";
        
        file_put_contents($testFile, $content);
        
        // 使用Windows打印命令
        $printerName = 'EPSON L4260 Series';
        $command = "print /D:\"$printerName\" \"$testFile\"";
        
        echo "   执行命令: $command\n";
        
        $output = [];
        $returnCode = 0;
        exec($command . ' 2>&1', $output, $returnCode);
        
        if ($returnCode === 0) {
            echo "   ✓ Windows系统打印命令执行成功\n";
        } else {
            echo "   ❌ Windows系统打印失败\n";
            echo "   输出: " . implode('\n', $output) . "\n";
        }
        
        // 清理测试文件
        if (file_exists($testFile)) {
            unlink($testFile);
        }
    }
    
    /**
     * 创建完整的打印测试
     */
    public function createPrintTest($printerUri) {
        echo "\n🖨️  创建 EPSON L4260 打印测试...\n";
        
        try {
            // 首先创建Printer对象
            $printer = $this->printerManager->findByUri($printerUri);
            if (!$printer) {
                echo "❌ 无法找到打印机: $printerUri\n";
                echo "💡 提示: 请确保打印机已连接并且CUPS服务正在运行\n";
                return null;
            }
            
            // 创建打印任务
            $job = new Job();
            $job->setName('EPSON L4260 完整测试');
            $job->setUsername('testuser');
            $job->setCopies(1);
            $job->setSides('one-sided');
            $job->setPrinterUri($printerUri);
            
            // 添加测试内容
            $testContent = $this->createTestContent();
            $job->addText($testContent);
            
            echo "✓ 打印任务创建成功\n";
            echo "  - 任务名称: " . $job->getName() . "\n";
            echo "  - 打印机URI: " . $job->getPrinterUri() . "\n";
            echo "  - 份数: " . $job->getCopies() . "\n";
            
            // 正确调用send方法：第一个参数是Printer对象，第二个参数是Job对象
            echo "\n📤 发送打印任务到打印机...\n";
            $result = $this->jobManager->send($printer, $job);
            
            if ($result) {
                echo "✅ 打印任务发送成功！\n";
                echo "📋 任务已提交到打印队列\n";
            } else {
                echo "❌ 打印任务发送失败\n";
            }
            
            return $job;
            
        } catch (Exception $e) {
            echo "❌ 创建打印任务失败: " . $e->getMessage() . "\n";
            echo "\n🔧 错误分析:\n";
            
            $message = $e->getMessage();
            if (strpos($message, 'Connection refused') !== false) {
                echo "- 连接被拒绝，可能是打印机未开启IPP服务\n";
                echo "- 建议：检查打印机网络设置，确保IPP协议已启用\n";
            } elseif (strpos($message, 'timeout') !== false) {
                echo "- 连接超时，可能是网络问题\n";
                echo "- 建议：检查网络连接，尝试ping打印机IP\n";
            } elseif (strpos($message, 'Host header') !== false) {
                echo "- Host header问题，这是常见的IPP连接问题\n";
                echo "- 建议：尝试使用改进的客户端修复此问题\n";
                return $this->createPrintTestWithImprovedClient($printerUri);
            } else {
                echo "- 未知错误，请检查打印机状态和网络连接\n";
            }
            
            return null;
        }
    }
    
    /**
     * 创建测试内容
     */
    private function createTestContent() {
        return "=== EPSON L4260 Series 打印测试 ===\n\n" .
               "打印机型号: EPSON L4260 Series\n" .
               "测试时间: " . date('Y-m-d H:i:s') . "\n" .
               "功能测试:\n" .
               "✓ 文本打印\n" .
               "✓ 中文字符: 爱普生打印机\n" .
               "✓ 特殊字符: @#$%^&*()\n\n" .
               "如果您能看到这个完整的测试页面，\n" .
               "说明EPSON L4260打印功能完全正常！";
    }
    
    /**
     * 使用改进的客户端创建打印测试（修复Host header问题）
     */
    public function createPrintTestWithImprovedClient($printerUri) {
        try {
            echo "\n🔧 尝试使用改进的客户端修复Host header问题...\n";
            
            // 从URI中提取IP地址
            $parsedUri = parse_url($printerUri);
            $printerIp = $parsedUri['host'] ?? '10.1.0.12';
            $printerPort = $parsedUri['port'] ?? 631;
            
            echo "   IP地址: {$printerIp}\n";
            echo "   端口: {$printerPort}\n";
            
            // 创建改进的客户端
            $improvedClient = ImprovedClient::createForIpAddress($printerIp, $printerPort);
            
            // 测试连接
            echo "🔍 测试网络连接: ";
            if (!$improvedClient->testConnection()) {
                echo "❌ 连接失败\n";
                return null;
            }
            echo "✅ 连接成功\n";
            
            // 使用改进的客户端创建管理器
            $improvedJobManager = new JobManager($this->builder, $improvedClient, $this->responseParser);
            $improvedPrinterManager = new PrinterManager($this->builder, $improvedClient, $this->responseParser);
            
            // 查找打印机
            echo "🖨️  查找打印机: ";
            $printer = $improvedPrinterManager->findByUri($printerUri);
            
            if (!$printer) {
                echo "❌ 未找到打印机\n";
                return null;
            }
            echo "✅ 找到打印机\n";
            
            // 创建Job对象
            $job = new Job();
            $job->setName('EPSON L4260 修复测试');
            $job->setUsername('testuser');
            $job->setCopies(1);
            $job->addText($this->createTestContent() . "\n\n✅ Host header问题已修复！");
            
            // 发送打印任务
            echo "📤 发送打印任务: ";
            $result = $improvedJobManager->send($printer, $job);
            
            if ($result) {
                echo "✅ 成功！\n";
                echo "🎉 Host header问题已成功修复！\n";
                return $job;
            } else {
                echo "❌ 失败\n";
                return null;
            }
            
        } catch (Exception $e) {
            echo "❌ 改进客户端也失败: {$e->getMessage()}\n";
            echo "\n🔄 尝试Windows系统打印作为备用方案...\n";
            return $this->windowsPrintFallback();
        }
    }
    
    /**
     * Windows系统打印备用方案
     */
    public function windowsPrintFallback() {
        if (PHP_OS_FAMILY !== 'Windows') {
            echo "❌ 当前系统不是Windows，无法使用系统打印\n";
            return null;
        }
        
        echo "🖥️  执行Windows系统打印...\n";
        
        $testContent = $this->createTestContent() . "\n\n✅ 使用Windows系统打印备用方案";
        $tempFile = tempnam(sys_get_temp_dir(), 'epson_fallback_');
        file_put_contents($tempFile, $testContent);
        
        $printerNames = [
            'EPSON L4260 Series',
            'EPSON L4260',
            'L4260 Series'
        ];
        
        foreach ($printerNames as $printerName) {
            echo "🖨️  尝试打印机: {$printerName} ";
            
            $command = "print /D:\"{$printerName}\" \"{$tempFile}\"";
            $output = [];
            $returnCode = 0;
            exec($command . ' 2>&1', $output, $returnCode);
            
            if ($returnCode === 0) {
                echo "✅ 成功\n";
                echo "🎉 Windows系统打印成功！\n";
                unlink($tempFile);
                
                // 创建一个虚拟Job对象用于返回
                $job = new Job();
                $job->setName('Windows系统打印');
                return $job;
            } else {
                echo "❌ 失败\n";
            }
        }
        
        unlink($tempFile);
        echo "❌ 所有Windows打印机名称都失败\n";
        return null;
    }
    
    /**
     * 显示EPSON L4260配置指南
     */
    public function showConfigurationGuide() {
        echo "\n" . str_repeat('=', 60) . "\n";
        echo "📋 EPSON L4260 Series 配置指南\n";
        echo str_repeat('=', 60) . "\n\n";
        
        echo "🔧 网络配置:\n";
        echo "1. 确保打印机连接到与电脑相同的网络\n";
        echo "2. 在打印机面板上打印网络状态页\n";
        echo "3. 记录打印机的IP地址\n\n";
        
        echo "🖥️  Windows配置:\n";
        echo "1. 控制面板 > 设备和打印机\n";
        echo "2. 添加打印机 > 网络打印机\n";
        echo "3. 选择 EPSON L4260 Series\n\n";
        
        echo "🌐 CUPS配置 (推荐):\n";
        echo "1. 访问 http://localhost:631\n";
        echo "2. Administration > Add Printer\n";
        echo "3. 选择 Internet Printing Protocol (ipp)\n";
        echo "4. 输入URI: ipp://[打印机IP]:631/ipp/print\n";
        echo "5. 选择EPSON驱动程序\n\n";
        
        echo "🧪 测试步骤:\n";
        echo "1. 运行网络检测: \$tester->detectNetworkConnection()\n";
        echo "2. 使用发现的URI创建测试: \$tester->createPrintTest(\$uri)\n";
        echo "3. 执行实际打印测试\n\n";
        
        echo "🔍 故障排除:\n";
        echo "- 检查网络连接: ping [打印机IP]\n";
        echo "- 检查防火墙设置\n";
        echo "- 重启打印机和路由器\n";
        echo "- 更新打印机驱动程序\n\n";
    }
    
    // 辅助方法
    private function pingHost($host, $timeout = 3) {
        if (PHP_OS_FAMILY === 'Windows') {
            $command = "ping -n 1 -w " . ($timeout * 1000) . " $host";
        } else {
            $command = "ping -c 1 -W $timeout $host";
        }
        
        $output = [];
        $returnCode = 0;
        exec($command . ' 2>&1', $output, $returnCode);
        
        return $returnCode === 0;
    }
    
    private function checkPort($host, $port, $timeout = 3) {
        $connection = @fsockopen($host, $port, $errno, $errstr, $timeout);
        if ($connection) {
            fclose($connection);
            return true;
        }
        return false;
    }
    
    private function getLocalIp() {
        if (PHP_OS_FAMILY === 'Windows') {
            $output = [];
            exec('ipconfig', $output);
            
            foreach ($output as $line) {
                if (strpos($line, 'IPv4') !== false && strpos($line, '192.168') !== false) {
                    preg_match('/\d+\.\d+\.\d+\.\d+/', $line, $matches);
                    if (!empty($matches)) {
                        return $matches[0];
                    }
                }
            }
        } else {
            $output = [];
            exec('hostname -I', $output);
            if (!empty($output)) {
                $ips = explode(' ', trim($output[0]));
                foreach ($ips as $ip) {
                    if (strpos($ip, '192.168') === 0) {
                        return $ip;
                    }
                }
            }
        }
        
        return null;
    }
}

// 执行测试
echo "=== EPSON L4260 Series 专用测试 ===\n\n";

$tester = new EpsonL4260Tester();

// 1. 显示配置指南
$tester->showConfigurationGuide();

// 2. 检测网络连接
$tester->detectNetworkConnection();

// 3. 创建测试任务示例
echo "\n🎯 创建测试任务示例...\n";
$exampleUri = 'ipp://10.1.0.12:631/ipp/print'; // 请替换为实际IP
$testJob = $tester->createPrintTest($exampleUri);

echo "\n✅ EPSON L4260 测试完成！\n";
echo "\n💡 提示: 请根据检测结果修改打印机URI，然后执行实际打印测试。\n";